package com.linc.concurrency;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;

public class CachedFactorizer extends HttpServlet {

  private BigInteger lastNumber;
  private BigInteger[] lastFactors;

  private long hits;
  private long cacheHits;

  @Override
  public void service(ServletRequest servletRequest, ServletResponse servletResponse)
      throws ServletException, IOException {
    BigInteger i = new BigInteger(servletRequest.getParameter("i"));
    BigInteger[] factors = null;

    synchronized (this) {
      ++hits;
      if (i.equals(lastNumber)) {
        factors = lastFactors.clone();
        cacheHits++;
      }
    }

    if (factors == null) {
      factors = factor(i);
      synchronized (this) {
        lastNumber = i;
        lastFactors = factors.clone();
      }
    }

    servletResponse.getWriter().append(Arrays.toString(factors));
  }

  private BigInteger[] factor(BigInteger i) {
    var r = new BigInteger[i.intValue()];
    r[0] = r[1] = BigInteger.valueOf(1);
    for (int j = 2; j < r.length; j++) {
      r[j] = r[j - 1].add(r[j - 2]);
    }
    return r;
  }
}
